<?php

namespace app\base\command;


use app\base\model\RedianData;
use app\base\model\RedianTask;
use app\base\service\TaskService;
use app\base\service\WsSendService;
use think\admin\Command;
use think\console\Input;
use think\console\Output;
/**
 * 定时任务推送数据到设备
 * Class SmsNum
 * @package app\common\command
 */
class TaskPush extends Command
{
    /**
     * 配置指令
     */
    protected function configure()
    {
        $this->setName('xbase:TaskPush');
        $this->setDescription('TaskPush');
    }

    protected function execute(Input $input, Output $output)
    {
        $queue_data = $this->queue->data;
        $task_id = $queue_data['task_id'];
        $task_run_log_id = $queue_data['task_run_log_id'];
        $this->setQueueProgress("任务ID_{$task_id}：开始执行");
        $task = RedianTask::mQuery()->where([ "id"=>$task_id])->find();
        $flag = true;
        $num = 1;
        $this->insetLog(1, $task_id, "推送数据到设备  ", $task_run_log_id);
        $status = 1;
        if($task['status']==0){
            $status = 0;
        }
        while ($flag){
            $this->setQueueProgress("任务ID_{$task_id}：执行第{$num}次");
            $this->insetLog(1, $task_id, "第{$num}次推送数据到设备  ", $task_run_log_id);
            $num++;
            if($task['push_schedule'] && $task['is_auto_fb']==1){
                $schedule = json_decode($task['push_schedule'],true);
                foreach ($schedule as $v){
                    $run_script = [];
                    if($task['is_auto_jjjb']==1){
                        $run_script[]=$this->app->db->name("script_confg")->where('type',0)->value('name');
                    }
                    if($task['is_auto_fbjb']==1){
                        $fb_jb=$this->app->db->name("script_confg")->whereIn('type',$v['platform'])->column('name');
                        foreach ($fb_jb as $item){
                            $run_script[]=$item;
                        }
                    }
                    foreach ($v['target_device'] as $v2){
                        //判断设备是否在线
                        $device = $this->app->db->name("ai_device")->where(['id'=>$v2])->find();
                        if($device){
                            if($device['status']==0){
                                $this->insetLog(1, $task_id, "设备不在线,等待设备上线  ", $task_run_log_id);
                                $this->app->db->name("redian_push_log")->insert([
                                    'task_id' => $task['id'],
                                    'user_id' => $task['user_id'],
                                    'error_msg' => "设备不在线",
                                    'status'=>0
                                ]);
                                $this->setQueueProgress("任务ID_{$task_id}_{$v2}：设备不在线");
                                //$output->info("推送失败_{$schedule['id']}：设备不在线");
                                break;
                            }
                            if($device['work_status']==2 && (time()-strtotime($device['last_run_time']))<1800){
                                $this->insetLog(1, $task_id, "设备不在线,等待设备上线  ", $task_run_log_id);
                                $this->app->db->name("redian_push_log")->insert([
                                    'task_id' => $task['id'],
                                    'user_id' => $task['user_id'],
                                    'error_msg' => "设备繁忙",
                                    'status'=>0
                                ]);
                                $this->setQueueProgress("任务ID_{$task_id}_{$v2}：设备繁忙");
                                break;
                            }

                            $this->pushData($task_id,$v2,$v['platform'],$task_run_log_id,$run_script);
                            $this->insetLog(1, $task_id, "数据已推送到设备,等待设备处理  ", $task_run_log_id);
                        }

                    }

                }

                //判断该任务的所有数据是否推送完成
                $c = $this->app->db->name("redian_data")
                    ->where([
                        'task_id'=>$task_id,
                        'task_run_log_id'=>$task_run_log_id,
                        'is_flish'=>0,
                        'video_status'=>3
                    ])->where('push_num','<',6)->count();
                if($c==0){
                    $flag = false;
                    $this->insetLog(1, $task_id, "设备处理数据完成", $task_run_log_id);

                    $this->app->db->name("redian_task")->where(['id'=>$task_id])->update(['progress'=>7,'status'=>$status]);
                    $this->app->db->name("task_run_log")->where(['id'=>$task_run_log_id])->update(['progress'=>7]);
                }
                $this->insetLog(1, $task_id, "数据已推送到设备,等待设备处理  ", $task_run_log_id);
                $this->setQueueProgress("任务未完成,等待下一个任务");
                sleep(60);

            }else{
                $flag = false;
            }
            if($num>60){
                $flag = false;

            }
        }
        $this->app->db->name("redian_task")->where(['id'=>$task_id])->update(['progress'=>7,'status'=>$status]);
        $this->app->db->name("task_run_log")->where(['id'=>$task_run_log_id])->update(['progress'=>7]);

        $this->setQueueSuccess("任务完成");


    }

    public function insetLog($type,$task_id,$msg='',$task_run_log_id=0)
    {
        $this->app->db->name("task_log")->insert([
            'type'=>$type,
            'task_id'=>$task_id,
            'task_run_log_id'=>$task_run_log_id,
            'content'=>$msg
        ]);
    }

    protected function pushData($task_id,$target_device,$platform,$task_run_log_id,$run_script)
    {
        $this->app->db->startTrans();
        try {
            $dataIds = $this->app->db->name("redian_data")
                ->where([
                    'task_id'=>$task_id,
                    'task_run_log_id'=>$task_run_log_id,
                    'is_flish'=>0,
                    'video_status'=>3
                ])->where('push_num','<',6)
                ->whereTime('push_time','<',date('Y-m-d H:i:s',time()-1000))
                ->limit(1)->column('id');
            if (empty($dataIds)) {
                // 提交事务
                $this->app->db->commit();
                return true;
            }
            $this->app->log->info("推送数据_{$task_id}：开始执行,执行脚本:" . json_encode($run_script));
            //获取对应平台执行脚本
            if(isset($run_script[0])){
                $script_file = $run_script[0];
                $next_script_file = "";
                if(isset($run_script[1])){
                    $next_script_file = $run_script[1];
                }
                $this->setQueueProgress("推送数据脚本_{$task_id}：{$script_file}",0);
                foreach ($dataIds as $dataId){
                    $content = [
                        'type'=>1,
                        'script_files'=>$run_script,
                        'script_file'=>$script_file,
                        'next_script_file'=>$next_script_file,
                        'data_id'=>$dataId,
                        'is_update'=>1
                    ];
                    WsSendService::instance()->send($target_device,1,$content);
                    $this->setQueueProgress("推送数据_{$task_id}：".json_encode($content));

                }
                //将设备设置成繁忙
                $this->app->db->name("ai_device")->where(['id'=>$target_device])->update([
                    'work_status'=>2,
                    'last_run_time' => date('Y-m-d H:i:s')
                ]);
                // 更新推送次数及数据推送的设备 平台
                $this->app->db->name("redian_data")->whereIn('id',$dataIds)->inc('push_num',1)->update([
                    'is_push'=>1,
                    'schedule_id'=>$target_device,
                    'platform'=>$platform,
                    'run_script'=>json_encode($run_script),
                    'push_time'=>date('Y-m-d H:i:s'),
                ]);
                $this->setQueueProgress("推送_{$task_id}-{$target_device}：成功");
                $this->output->info("推送_{$task_id}-{$target_device}：成功");
                // 提交事务
                $this->app->db->commit();
                return true;
            }
        } catch (\Exception $e) {
            $this->app->db->rollback();
            $this->setQueueProgress("推送失败_{$task_id}-{$target_device}：{$e->getMessage()}");
            //$this->output->info("推送失败_{$schedule['id']}：{$e->getMessage()}");
            //  $this->app->log->error("推送失败_{$schedule['id']}：{$e->getMessage()}");
            return true;
          //  throw $e;
        }
        return true;

    }



}
